#pragma once
#include "libs.cpp"

namespace json::detail {
    template <typename Str, typename Str2>
    constexpr bool equals_impl() {
        if (Str::size != Str2::size)
            return false;
        for (size_t i = 0; i < Str::size; ++i) {
            if (Str::value[i] != Str2::value[i])
                return false;
        }
        return true;
    }
    template <size_t N>
    struct compile_string_impl {
        static constexpr inline auto size = N;
        char content[N];
        constexpr compile_string_impl(const char s[N]) {
            for (size_t i = 0; i < N; ++i) {
                content[i] = s[i];
            }
        }
    };
    template <size_t N>
    compile_string_impl(const char s[N]) -> compile_string_impl<N>;
    template <typename S, size_t Offset, size_t Size>
    struct part_compile_string;
    template <compile_string_impl S>
    struct pure_compile_string {
        static constexpr inline const char *value = S.content;
        static constexpr inline size_t size = decltype(S)::size;
        template <size_t Offset, size_t Size>
        using sub = part_compile_string<pure_compile_string, Offset, Size>;
        template <typename Str>
        static constexpr inline bool equals = equals_impl<pure_compile_string, Str>();
    };
    template <typename>
    static constexpr inline bool is_pure_compile_string_v = false;
    template <compile_string_impl S>
    static constexpr inline bool is_pure_compile_string_v<pure_compile_string<S>> = true;
    template <typename S, size_t Offset, size_t Size>
    struct part_compile_string {
        static_assert(is_pure_compile_string_v<S>, "Must be compile_string");
        static constexpr inline const char *value = S::value + Offset;
        static constexpr inline size_t size = Size;
        template <size_t Offset2, size_t Size2>
        using sub = part_compile_string<S, Offset + Offset2, Size2>;
        template <typename Str>
        static constexpr inline bool equals = equals_impl<part_compile_string, Str>();
    };
    template <typename>
    static constexpr inline bool is_part_compile_string_v = false;
    template <typename S, size_t Offset, size_t Size>
    static constexpr inline bool is_part_compile_string_v<part_compile_string<S, Offset, Size>> = true;
};
namespace json {
    template <typename T>
    concept compile_string = requires(T) {
        std::is_same_v<size_t, decltype(T::size)>;
        std::is_same_v<const char *, decltype(T::value)>;

    };
}
#define JSON_MAKE_STRING(s) decltype(([] { \
    constexpr std::string_view str{s}; \
    return ::json::detail::pure_compile_string<::json::detail::compile_string_impl<str.size()>{s}>{}; \
})())
#define JSON_REMOVE_BRACKET_IMPL(...) __VA_ARGS__
#define JSON_REMOVE_BRACKET(arg) JSON_REMOVE_BRACKET_IMPL arg
#define JSON_MACRO_TO_STRING(s) #s
#define JSON_MAKE_STRING_TYPE(s) JSON_MAKE_STRING(JSON_MACRO_TO_STRING(JSON_REMOVE_BRACKET(s)))
